home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / x2ftp / msdos / source / gfxfx / x3dunit.pas < prev   
Pascal/Delphi Source File  |  1994-06-18  |  6KB  |  209 lines

  1.  
  2. unit x3dunit;
  3. { mode-x 3D unit - xhlin-procedure by Sean Palmer }
  4. interface
  5.  
  6. const
  7.   vidseg:word=$a000;
  8.   divd:word=128;
  9.   dist:word=200;
  10.   border:boolean=false;
  11.  
  12. var
  13.   ctab,stab:array[0..255] of integer;
  14.   minx,miny,maxx,maxy:integer;
  15.   address:word;
  16.  
  17. procedure setborder(col:byte);
  18. procedure setpal(c,r,g,b:byte);
  19. procedure retrace;
  20. procedure setmodex;
  21. procedure setaddress(ad:word);
  22. procedure cls;
  23. procedure polygon(x1,y1,x2,y2,x3,y3,x4,y4:integer; c:byte);
  24. function cosinus(i:byte):integer;
  25. function sinus(i:byte):integer;
  26.  
  27. implementation
  28.  
  29. procedure setborder(col:byte); assembler; asm
  30.   xor ch,ch; mov cl,border; jcxz @out; mov dx,3dah; in al,dx
  31.   mov dx,3c0h; mov al,11h+32; out dx,al; mov al,col; out dx,al; @out: end;
  32.  
  33. procedure setpal(c,r,g,b:byte); assembler; asm
  34.   mov dx,3c8h; mov al,[c]; out dx,al; inc dx; mov al,[r]
  35.   out dx,al; mov al,[g]; out dx,al; mov al,[b]; out dx,al; end;
  36.  
  37. procedure retrace; assembler; asm
  38.   mov dx,3dah; @vert1: in al,dx; test al,8; jz @vert1
  39.   @vert2: in al,dx; test al,8; jnz @vert2; end;
  40.  
  41. procedure setmodex; assembler; asm
  42.   mov ax,13h; int 10h; mov dx,3c4h; mov ax,0604h; out dx,ax; mov ax,0f02h
  43.   out dx,ax; mov cx,320*200; mov es,vidseg; xor ax,ax; mov di,ax; rep stosw
  44.   mov dx,3d4h; mov ax,0014h; out dx,ax; mov ax,0e317h; out dx,ax; end;
  45.  
  46. procedure setaddress(ad:word); assembler; asm
  47.   mov dx,3d4h; mov al,0ch; mov ah,[byte(ad)+1]; out dx,ax
  48.   mov al,0dh; mov ah,[byte(ad)]; out dx,ax; end;
  49.  
  50. procedure cls; assembler; asm
  51.   mov es,vidseg; mov di,address; mov cx,8000; mov dx,3c4h
  52.   mov ax,0f02h; out dx,ax; xor ax,ax; rep stosw; end;
  53.  
  54. procedure xhlin(x,x2,y:integer;c:byte); assembler;
  55. asm
  56.   mov ax,vidseg
  57.   mov es,ax
  58.   cld
  59.   mov ax,80
  60.   mul y
  61.   mov di,ax             { base of scan line }
  62.   add di,address
  63.   mov bx,[x]
  64.   mov dx,[x2]
  65.   cmp bx,dx
  66.   jb @skip
  67.   xchg bx,dx
  68.  @skip:
  69.   mov cl,bl
  70.   shr bx,2
  71.   mov ch,dl
  72.   shr dx,2
  73.   and cx,$0303
  74.   sub dx,bx             { width in Bytes }
  75.   add di,bx             { offset into video buffer }
  76.   mov ax,$ff02
  77.   shl ah,cl
  78.   and ah,$0f            { left edge mask }
  79.   mov cl,ch
  80.   mov bh,$f1
  81.   rol bh,cl
  82.   and bh,$0f            { right edge mask }
  83.   mov cx,dx
  84.   or cx,cx
  85.   jnz @left
  86.   and ah,bh             { combine left & right bitmasks }
  87.  @left:
  88.   mov dx,$03c4
  89.   out dx,ax
  90.   inc dx
  91.   mov al,[c]
  92.   stosb
  93.   jcxz @exit
  94.   dec cx
  95.   jcxz @right
  96.   mov al,$0f
  97.   out dx,al             { skipped if cx=0,1 }
  98.   mov al,[c]
  99.   repz stosb            { fill middle Bytes }
  100.  @right:
  101.   mov al,bh
  102.   out dx,al             { skipped if cx=0 }
  103.   mov al,[c]
  104.   stosb
  105.  @exit:
  106. end;
  107.  
  108. function maxi(a,b:integer):integer; inline(
  109.   $58/             { pop   ax     }
  110.   $5b/             { pop   bx     }
  111.   $3b/$c3/         { cmp   ax,bx  }
  112.   $7f/$01/         { jg    +1     }
  113.   $93);            { xchg  ax,bx  }
  114.  
  115. function mini(a,b:integer):integer; inline(
  116.   $58/             { pop   ax     }
  117.   $5b/             { pop   bx     }
  118.   $3b/$c3/         { cmp   ax,bx  }
  119.   $7c/$01/         { jl    +1     }
  120.   $93);            { xchg  ax,bx  }
  121.  
  122. function inrangei(value,min,max:integer):integer; inline(
  123.   $59/             { pop   cx max }
  124.   $5b/             { pop   bx min }
  125.   $58/             { pop   ax val }
  126.   $3b/$c3/         { cmp   ax,bx  }
  127.   $7f/$03/         { jg    +3     }
  128.   $93/             { xchg  ax,bx  }
  129.   $eb/$05/         { jmp   +5     }
  130.   $3b/$c1/         { cmp   ax,cx  }
  131.   $7c/$01/         { jl    +1     }
  132.   $91);            { xchg  ax,cx  }
  133.  
  134. procedure polygon( x1,y1, x2,y2, x3,y3, x4,y4 :integer; c:byte);
  135. var pos:array[0..199,0..1] of integer;
  136.   xdiv1,xdiv2,xdiv3,xdiv4:integer;
  137.   ydiv1,ydiv2,ydiv3,ydiv4:integer;
  138.   dir1,dir2,dir3,dir4:byte;
  139.   ly,gy,y,tmp,step:integer;
  140. begin
  141.   { determine highest and lowest point + vertical window checking }
  142.   ly:=maxi(mini(mini(mini(y1,y2),y3),y4),miny);
  143.   gy:=mini(maxi(maxi(maxi(y1,y2),y3),y4),maxy);
  144.   if ly>maxy then exit;
  145.   if gy<miny then exit;
  146.  
  147.   { check directions (-1=down, 1=up) and calculate constants }
  148.   dir1:=byte(y1<y2); xdiv1:=x2-x1; ydiv1:=y2-y1;
  149.   dir2:=byte(y2<y3); xdiv2:=x3-x2; ydiv2:=y3-y2;
  150.   dir3:=byte(y3<y4); xdiv3:=x4-x3; ydiv3:=y4-y3;
  151.   dir4:=byte(y4<y1); xdiv4:=x1-x4; ydiv4:=y1-y4;
  152.  
  153.   y:=y1;
  154.   step:=dir1*2-1;
  155.   if y1<>y2 then repeat
  156.     if inrangei(y,ly,gy)=y then begin
  157.       tmp:=xdiv1*(y-y1) div ydiv1+x1;
  158.       pos[y,dir1]:=inrangei(tmp,minx,maxx);
  159.     end;
  160.     inc(y,step);
  161.   until y=y2+step
  162.   else if (y>=ly) and (y<=gy) then pos[y,dir1]:=inrangei(x1,minx,maxx);
  163.  
  164.   y:=y2;
  165.   step:=dir2*2-1;
  166.   if y2<>y3 then repeat
  167.     if inrangei(y,ly,gy)=y then begin
  168.       tmp:=xdiv2*(y-y2) div ydiv2+x2;
  169.       pos[y,dir2]:=inrangei(tmp,minx,maxx);
  170.     end;
  171.     inc(y,step);
  172.   until y=y3+step
  173.   else if (y>=ly) and (y<=gy) then pos[y,dir2]:=inrangei(x2,minx,maxx);
  174.  
  175.   y:=y3;
  176.   step:=dir3*2-1;
  177.   if y3<>y4 then repeat
  178.     if inrangei(y,ly,gy)=y then begin
  179.       tmp:=xdiv3*(y-y3) div ydiv3+x3;
  180.       pos[y,dir3]:=inrangei(tmp,minx,maxx);
  181.     end;
  182.     inc(y,step);
  183.   until y=y4+step
  184.   else if (y>=ly) and (y<=gy) then pos[y,dir3]:=inrangei(x3,minx,maxx);
  185.  
  186.   y:=y4;
  187.   step:=dir4*2-1;
  188.   if y4<>y1 then repeat
  189.     if inrangei(y,ly,gy)=y then begin
  190.       tmp:=xdiv4*(y-y4) div ydiv4+x4;
  191.       pos[y,dir4]:=inrangei(tmp,minx,maxx);
  192.     end;
  193.     inc(y,step);
  194.   until y=y1+step
  195.   else if (y>=ly) and (y<=gy) then pos[y,dir4]:=inrangei(x4,minx,maxx);
  196.  
  197.   for y:=ly to gy do xhlin(pos[y,0],pos[y,1],y,c);
  198. end;
  199.  
  200. function cosinus(i:byte):integer; begin cosinus:=ctab[i]; end;
  201. function sinus(i:byte):integer; begin sinus:=stab[i]; end;
  202.  
  203. var i:byte;
  204. begin
  205.   minx:=0; miny:=0; maxx:=319; maxy:=199;
  206.   for i:=0 to 255 do ctab[i]:=round(-cos(i*pi/128)*divd);
  207.   for i:=0 to 255 do stab[i]:=round(sin(i*pi/128)*divd);
  208. end.
  209.